import appConfig from '@/appConfig'
import store from "@/store";
import md5 from "@/vendor/md5";
import utils from "@/libs/utils";
import Storage from "@/libs/Storage";

export const tokenManager = {
  init() {
    if (this.token) {
      return this.token
    }

    this.token = Storage.getSync('token')
  },
  setToken(token) {
    if (token !== this.token) {
      Storage.set('token', token);
    }

    this.token = token
  },

  clear() {
    this.token = null
  }
}

class Http {
  constructor(inited = false) {
    this.inited = inited
    this.cached = []
    tokenManager.init()
  }

  async static(url, obj = {}) {
    const start = Date.now()
    if (obj.key) {
      const res = await Storage.get(obj.key)
      // console.log('res', res)
      if (res && res.url === url) {
        const data = utils.decrypt(res.data)
        console.log('耗时', url, Date.now() - start)
        return {
          data, url
        }
      }
    }

    return new Promise(resolve => {
      uni.request({
        url,
        success: (res) => {
          Storage.set(obj.key, {data: res.data, url})
          const data = utils.decrypt(res.data)

          resolve({data, url})
          console.log('耗时', url, Date.now() - start)
        }
      })
    })
  }

  get(url, object = {}) {
    object.method = 'GET'
    object.url = url
    return this.request(object)
  }

  post(url, object = {}) {
    object.method = 'POST'
    object.url = url

    return this.request(object)
  }

  delete(url, object = {}) {
    object.url = url
    object.method = 'DELETE'
    return this.request(object)
  }

  put(url, object = {}) {
    object.url = url
    object.method = 'PUT'
    return this.request(object)
  }

  _waitInit(object) {
    console.log('===wait', object)
    return new Promise(resolve => {
      this.cached.push({
        object,
        resolve
      })
    })
  }

  async init() {
    this.inited = true
    for (let i = 0; i < this.cached.length; i++) {
      await this.cached[i].resolve()
    }
  }

  async request(object) {
    object = Object.assign({log: true, basePath: '/api/jiakao/', returnRequest: false}, object)

    object.url = appConfig.api + object.basePath + object.url
    object.withCredentials = true
    object.header = Object.assign({}, object.header)


    if (!this.inited) {
      await this._waitInit(object)
    }

    // console.log('xxxxx', tokenManager.token)
    if (tokenManager.token) {
      object.header[appConfig.tokenKey] = tokenManager.token
    }
    // console.log('token', tokenManager.token)

    let signValue = '';
    ['deviceBrand', 'appVersionCode', 'osName', 'uniPlatform', 'appId', 'osVersion', 'deviceModel'].map(item => {
      const value = store.getters.systemInfo[item] || ''
      object.header[item] = value
      signValue += value
    })

    object.header['page'] = utils.getCurrentPage() || 'empty'
    object.header['pagePath'] = utils.getCurrentPageWithParams() || 'empty'
    object.header['prevPagePath'] = utils.getPrevPageWithParams() || 'empty'
    object.header['appChannel'] = store.getters.systemInfo['appChannel'] || ''
    object.header['adChannel'] = store.getters.systemInfo['adChannel'] || ''
    object.header['wgtVersionCode'] = store.getters.systemInfo['wgtVersionCode']
    object.header['clientVersionCode'] = store.getters.systemInfo['clientVersionCode']
    object.header['uniRuntimeVersion'] = store.getters.systemInfo['uniRuntimeVersion']
    object.header['mpAppId'] = store.getters.systemInfo['mpAppId'] || ''
    object.header['androidId'] = store.getters.systemInfo['androidId'] || ''
    object.header['imei'] = store.getters.systemInfo['imei'] || ''
    object.header['oaid'] = store.getters.systemInfo['oaid'] || ''
    object.header['ua'] = store.getters.systemInfo['ua'] || ''
    object.header['carType'] = store.getters.carType
    object.header['jwtSess'] = 1
    object.header['packageName'] = store.getters.systemInfo['packageName'] || ''
    if (store.getters.location) {
      object.header['location'] = store.getters.location['code'] || ''
    }


    const t = Date.now()
    const sign = md5(t + signValue + appConfig.key)
    object.header['sign'] = sign
    object.header['t'] = t
    if (object.returnRequest) {
      return object
    }

    return new Promise((resolve, reject) => {
      if (object.log) {
        console.info('===start', object)
      }

      uni.request({
        ...object,
        success: (res) => {
          if (res.data.status === 0) {
            if (object.log) {
              console.info('===succ', res)
            }
            const {tokenKey} = appConfig
            const firstTokenKey = tokenKey.charAt(0).toUpperCase() + tokenKey.slice(1)
            // console.log('firstTokenKey', firstTokenKey, tokenKey)
            const token = res.header[tokenKey] || res.header[firstTokenKey]
            if (token) {
              tokenManager.setToken(token)
            }
            resolve(res)
          } else {
            if (object.log) {
              console.error('===error', res, object)
            }
            res.message = res.data.msg
            reject(res)
          }
        },
        fail(res) {
          console.error('error', res)
          reject(res)
        }
      })
    })
  }
}

export default Http
